﻿/*
Copyright (c) 2007-2011 William POTTIER - AllProgrammic

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
of the Software, and to permit persons to whom the Software is furnished to do so, 
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all 
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System.Net;
using NetAccess.Utils;

namespace NetAccess.Common
{
    /// <summary>
    /// Base configuration class
    /// </summary>
    public abstract class NetConfiguration
    {
        #region Fields
        /// <summary>
        /// true if the configuration cannot be edited
        /// </summary>
        protected bool Locked;

        /// <summary>
        /// application identifier
        /// </summary>
        private string _applicationIdentifier = "";

        /// <summary>
        /// send buffer size
        /// </summary>
        private int _sendbuffersize = 8192;

        /// <summary>
        /// receive buffer size
        /// </summary>
        private int _receivebuffersize = 8192;
        
        /// <summary>
        /// ip address to listen service discovery
        /// </summary>
        private IPAddress _serviceDiscoveryIP;

        /// <summary>
        /// port for service discovery
        /// </summary>
        private int _serviceDiscoveryPort = 14351;

        /// <summary>
        /// In server context, IPAddress to listen; in client context, ip to connect
        /// </summary>
        private IPAddress _ip = IPAddress.Any;

        /// <summary>
        /// tcp service port
        /// </summary>
        private int _tcpServicePort;

        /// <summary>
        /// udp service port
        /// </summary>
        private int _udpServicePort;

        /// <summary>
        /// Enable message encryption
        /// </summary>
        private bool _isEnableEnryption;

        /// <summary>
        /// RSA private key
        /// </summary>
        private byte[] _privateKey;

        /// <summary>
        /// RSA publish key
        /// </summary>
        private byte[] _publicKey;
        #endregion

        #region Properties
        /// <summary>
        /// Application Identifier
        /// </summary>
        public string ApplicationIdentifier
        {
            get
            { return _applicationIdentifier; }
            set
            {
                if (Locked) return;
                _applicationIdentifier = value;
            }
        }

        /// <summary>
        /// Gets or sets the size of the send buffer.
        /// </summary>
        /// <value>The size of the send buffer.</value>
        public int SendBufferSize
        {
            get
            { return _sendbuffersize; }
            set
            {
                if (Locked) return;
                _sendbuffersize = value;
            }
        }

        /// <summary>
        /// Gets or sets the size of the receive buffer.
        /// </summary>
        /// <value>The size of the receive buffer.</value>
        /// <remarks></remarks>
        public int ReceiveBufferSize
        {
            get
            { return _receivebuffersize; }
            set
            {
                if (Locked) return;
                _receivebuffersize = value;
            }
        }

        /// <summary>
        /// Get autodiscover Endpoint
        /// </summary>
        /// <remarks></remarks>
        public EndPoint ServiceDiscoveryEndPoint { get; private set; }

        /// <summary>
        /// Get or Set the discovery port
        /// </summary>
        /// <value>The discovery port.</value>
        /// <remarks></remarks>
        public int ServiceDiscoveryPort
        {
            get
            { return _serviceDiscoveryPort; }
            set
            {
                if (Locked) return;
                _serviceDiscoveryPort = value;
                ServiceDiscoveryEndPoint = new IPEndPoint(_serviceDiscoveryIP, _serviceDiscoveryPort);
            }
        }

        /// <summary>
        /// Get or set the ip to listen for discovery port
        /// </summary>
        /// <value>The discovery IP.</value>
        /// <remarks></remarks>
        public IPAddress ServiceDiscoveryIP
        {
            get { return _serviceDiscoveryIP; }
            set
            {
                if (Locked) return;
                _serviceDiscoveryIP = value;
                ServiceDiscoveryEndPoint = new IPEndPoint(_serviceDiscoveryIP, _serviceDiscoveryPort);
            }
        }

        /// <summary>
        /// Ip d'écoute ou de connexion
        /// </summary>
        /// <value>The IP.</value>
        /// <remarks></remarks>
        public IPAddress IP
        {
            get
            { return _ip; }
            set
            {
                if (Locked) return;
                _ip = value;
                TCPServiceEndPoint = new IPEndPoint(_ip, _tcpServicePort);
                UDPServiceEndPoint = new IPEndPoint(_ip, UDPServicePort);
            }
        }

        /// <summary>
        /// Port TCP
        /// </summary>
        /// <value>The TCP port.</value>
        /// <remarks></remarks>
        public int TCPServicePort
        {
            get
            { return _tcpServicePort; }
            set
            {
                if (Locked) return;
                _tcpServicePort = value;
                TCPServiceEndPoint = new IPEndPoint(IP, _tcpServicePort);
            }
        }

        /// <summary>
        /// End point TCP
        /// </summary>
        /// <remarks></remarks>
        public IPEndPoint TCPServiceEndPoint { get; private set; }

        /// <summary>
        /// Direct UDP Port
        /// </summary>
        /// <value>The direct UDP port.</value>
        /// <remarks></remarks>
        public int UDPServicePort
        {
            get
            { return _udpServicePort; }
            set
            {
                if (Locked) return;
                _udpServicePort = value;
                UDPServiceEndPoint = new IPEndPoint(_ip, UDPServicePort);
            }
        }

        /// <summary>
        /// EndPoint pour le direct UDP
        /// </summary>
        /// <remarks></remarks>
        public EndPoint UDPServiceEndPoint { get; private set; }

        /// <summary>
        /// True if network stream encryption is active
        /// </summary>
        public bool IsEnableEncryption
        {
            get { return _isEnableEnryption; }
            set
            {
                if (Locked) return;
                _isEnableEnryption = value;
            }
        }

        /// <summary>
        /// Private RSA key as byte array
        /// </summary>
        public byte[] PrivateKey
        {
            get { return _privateKey; }
            set
            {
                if (Locked) return;
                _privateKey = value;
            }
        }

        /// <summary>
        /// Private RSA key as string
        /// </summary>
        public string PrivateKeyString
        {
            get { return EncryptionManager.ConvertKeyToString(_privateKey); }
            set
            {
                if (Locked) return;
                _privateKey = EncryptionManager.ConvertKeyFromString(value);
            }
        }

        /// <summary>
        /// Public RSA key as byte array
        /// </summary>
        public byte[] PublicKey
        {
            get { return _publicKey; }
            set
            {
                if (Locked) return;
                _publicKey = value;
            }
        }

        /// <summary>
        /// Public RSA key as string
        /// </summary>
        public string PublicKeyString
        {
            get { return EncryptionManager.ConvertKeyToString(_publicKey); }
            set
            {
                if (Locked) return;
                _publicKey = EncryptionManager.ConvertKeyFromString(value);
            }
        }
        #endregion

        /// <summary>
        /// Locks the configuration.
        /// </summary>
        /// <remarks></remarks>
        internal void LockConfiguration()
        {
            Locked = true;
        }
    }
}
